<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\timer\model\groupon;

use app\common\library\helper;
use app\common\model\groupon\Task as TaskModel;
use app\timer\model\groupon\Goods as GrouponGoodsModel;
use app\common\enum\groupon\TaskStatus as TaskStatusEnum;
use app\timer\library\Tools;

/**
 * 拼团拼单模型
 * Class Task
 * @package app\timer\model\groupon
 */
class Task extends TaskModel
{
    /**
     * 获取已过期但未结束的拼单ID集
     * @param int $storeId
     * @return array
     */
    public function getFailTaskIds(int $storeId): array
    {
        return $this->where('end_time', '<=', time())
            ->where('status', '=', TaskStatusEnum::NORMAL)
            ->where('is_delete', '=', 0)
            ->where('store_id', '=', $storeId)
            ->column('task_id');
    }

    /**
     * 获取已完成的拼单ID集
     * @param int $storeId
     * @return array
     */
    public function getCompleteTaskIds(int $storeId): array
    {
        // 获取一小时内完成的拼单
        // 完成时间 > 当前时间 - 1小时
        return $this->where('complete_time', '>', time() - 60 * 60)
            ->where('status', '<>', TaskStatusEnum::NORMAL)
            ->where('is_delete', '=', 0)
            ->where('store_id', '=', $storeId)
            ->column('task_id');
    }

    /**
     * 将拼单任务状态标记结束
     * @param array $taskIds 拼单任务ID集
     * @return bool
     */
    public function setStatusFail(array $taskIds): bool
    {
        return static::updateBase([
            'complete_time' => time(),
            'status' => TaskStatusEnum::FAIL
        ], [['task_id', 'in', $taskIds]]);
    }

    /**
     * 获取模拟成团的拼单
     * @param int $storeId
     * @return \app\timer\model\groupon\Task[]|array|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getMockTaskList(int $storeId)
    {
        // 拼单过期时间需有一定间隔, 因要兼容定时任务的延时, 此处设置12分钟 (定时任务每10分钟执行 )
        $compatibleTime = time() + (12 * 60);
        // 查询满足条件的记录
        $groupGoodsName = GrouponGoodsModel::getTableName();
        return $this->alias($this->alias)
            ->field("$this->alias.*")
            ->join($groupGoodsName, "{$groupGoodsName}.groupon_goods_id = {$this->alias}.groupon_goods_id")
            ->where("{$groupGoodsName}.is_mock_task", '=', 1)
            ->where("{$this->alias}.end_time", '<=', $compatibleTime)
            ->where("{$this->alias}.end_time", '>', time())
            ->where("{$this->alias}.status", '=', TaskStatusEnum::NORMAL)
            ->where("{$this->alias}.is_delete", '=', 0)
            ->where("{$this->alias}.store_id", '=', $storeId)
            ->order(["{$this->alias}.end_time" => 'asc'])
            ->select();
    }

    /**
     * 指定的拼单模拟成团
     * @param \app\timer\model\groupon\Task $task
     * @param int $storeId
     * @return bool
     */
    public function mockTask(self $task, int $storeId): bool
    {
        // 剩余拼单人数
        $robotPeopleNum = $task['people'] - $task['actual_people'];
        // 获取随机的机器人成员ID集
        $robotIds = Robot::getRandomRobot($robotPeopleNum, $storeId);
        // 记录日志
        Tools::taskLogs('GrouponTask', 'mockTask', [
            'title' => '指定的拼单模拟成团',
            'taskId' => $task['task_id'],
            'robotPeopleNum' => $robotPeopleNum,
            'robotIds' => helper::jsonEncode($robotIds),
        ]);
        // 如果机器人数量小于模拟成团所需人数则不执行
        if (empty($robotIds)) {
            return false;
        }
        // 批量加入机器人成员
        TaskUsers::mockJoin($robotIds, $task, $storeId);
        // 更新拼单状态为已完成
        return $task->save([
            'robot_people' => $robotPeopleNum,
            'complete_time' => time(),
            'status' => TaskStatusEnum::SUCCESS
        ]);
    }
}